﻿/*
 * Copyright © 2020, Wuxi Safover Intelligent Technology Co., Ltd. All rights reserved.
 * 
 * 无锡安永智能科技有限公司版权所有，未经许可，不得用于商业用途
 * 
 * Visit: https://www.safover.com/ 
 */

using SafoverWpfFw;
using System;
using System.Windows.Input;
using Safover.LidarCollector.Models;
using Safover.Lidar.DataContract;

namespace Safover.LidarCollector.ViewModel
{
    public interface ISelectable 
    {
        bool IsSelected { get; set; }
    }

    public abstract class StepScanViewModel : BaseViewModel, ISelectable
    {
        public abstract LidarWorkMode LidarWorkMode { get; }

        public ICommand SwitchIsSelectedCommand { get; set; }

        /// <summary>
        /// ViewModel中使用，标记是否被选中用于CRUD操作
        /// </summary>
        public bool IsSelected { get; set; }

        public TimeSpan PeriodScanEndDelayDuration { get; set; }

        public TimeSpan SingleScanEndDelayDuration { get; set; }


        public TimeSpan TotalScanDuration { get; set; }

        public StepScanViewModel(SingleScanConfig config)
        {
            PeriodScanEndDelayDuration = config.PeriodScanEndDelayDuration;
            SingleScanEndDelayDuration = config.SingleScanEndDelayDuration;
            TotalScanDuration = config.TotalScanDuration;

            SwitchIsSelectedCommand = new RelayCommand(() => IsSelected ^= true);
        }

        public abstract SingleScanConfig ToConfig();

        public override string ToString()
        {
            return $"{LidarWorkMode}: TotalScanDuration=[{TotalScanDuration}]; PeriodScanEndDelayDuration=[{PeriodScanEndDelayDuration}]; EndDelayDuration=[{SingleScanEndDelayDuration}; ";
        }

    }

    public class VerticalScanConfigViewModel : StepScanViewModel
    {
        public VerticalScanConfigViewModel(VerticalScanConfig config) : base(config)
        {
            VerticalStartAngle = config.VerticalStartAngle;
            VerticalRangeAngle = config.VerticalRangeAngle;
            VerticalStepAngle = config.VerticalStepAngle;

            FixedHorizontalAngle = config.FixedHorizontalAngle;
        }

        public override LidarWorkMode LidarWorkMode => LidarWorkMode.Vertical;

        public float VerticalStartAngle { get; set; }

        public float VerticalRangeAngle { get; set; }

        public float VerticalStepAngle { get; set; }

        public float FixedHorizontalAngle { get; set; }
        

        public override SingleScanConfig ToConfig()
        {
            return new VerticalScanConfig
            {
                PeriodScanEndDelayDuration = PeriodScanEndDelayDuration,
                SingleScanEndDelayDuration = SingleScanEndDelayDuration,
                TotalScanDuration = TotalScanDuration,

                VerticalStartAngle = VerticalStartAngle,
                VerticalRangeAngle = VerticalRangeAngle,
                VerticalStepAngle = VerticalStepAngle,

                FixedHorizontalAngle = FixedHorizontalAngle,
            };
        }
    }

    public class HorizontalScanConfigViewModel : StepScanViewModel
    {
        public HorizontalScanConfigViewModel(HorizontalScanConfig config) : base(config)
        {
            HorizontalStartAngle = config.HorizontalStartAngle;
            HorizontalRangeAngle = config.HorizontalRangeAngle;
            HorizontalStepAngle = config.HorizontalStepAngle;

            FixedVertialAngle = config.FixedVertialAngle;
        }

        public override LidarWorkMode LidarWorkMode => LidarWorkMode.Horizontal;

        public float HorizontalStartAngle { get; set; }

        public float HorizontalRangeAngle { get; set; }

        public float HorizontalStepAngle { get; set; }

        public float FixedVertialAngle { get; set; }
        

        public override SingleScanConfig ToConfig()
        {
            return new HorizontalScanConfig
            {
                PeriodScanEndDelayDuration = PeriodScanEndDelayDuration,
                SingleScanEndDelayDuration = SingleScanEndDelayDuration,
                TotalScanDuration = TotalScanDuration,

                HorizontalStartAngle = HorizontalStartAngle,
                HorizontalRangeAngle = HorizontalRangeAngle,
                HorizontalStepAngle = HorizontalStepAngle,

                FixedVertialAngle = FixedVertialAngle,
            };
        }
    }

    public class FixedScanConfigViewModel : StepScanViewModel
    {
        public FixedScanConfigViewModel(FixedDirectionScanConfig config) : base(config)
        {
            FixedHorizontalAngle = config.HorizontalAngle;
            FixedVertialAngle = config.VertialAngle;
        }

        public override LidarWorkMode LidarWorkMode => LidarWorkMode.Fixed;

        public float FixedVertialAngle { get; set; }

        public float FixedHorizontalAngle { get; set; }

        public override SingleScanConfig ToConfig()
        {
            return new FixedDirectionScanConfig
            {
                PeriodScanEndDelayDuration = PeriodScanEndDelayDuration,
                SingleScanEndDelayDuration = SingleScanEndDelayDuration,
                TotalScanDuration = TotalScanDuration,

                VertialAngle = FixedVertialAngle,
                HorizontalAngle = FixedHorizontalAngle,
            };
        }
    }

    public class UnderwayConfigViewModel : StepScanViewModel
    {
        public UnderwayConfigViewModel(UnderwayScanConfig config) : base(config)
        {
            UnderwayHorizontalAngle = config.HorizontalAngle;
            UnderwayVertialAngle = config.VertialAngle;
        }

        public override LidarWorkMode LidarWorkMode => LidarWorkMode.Underway;

        public float UnderwayVertialAngle { get; set; }

        public float UnderwayHorizontalAngle { get; set; }

        public override SingleScanConfig ToConfig()
        {
            return new UnderwayScanConfig
            {
                PeriodScanEndDelayDuration = PeriodScanEndDelayDuration,
                SingleScanEndDelayDuration = SingleScanEndDelayDuration,

                VertialAngle = UnderwayVertialAngle,
                HorizontalAngle = UnderwayVertialAngle,
            };
        }
    }

    public class BlindSectorViewModel : BaseViewModel, IComparable, ISelectable
    {
        /// <summary>
        /// ViewModel中使用，标记是否被选中用于CRUD操作
        /// </summary>
        public bool IsSelected { get; set; }

        /// <summary>
        /// 屏蔽区起始角
        /// </summary>
        public float StartAngle { get; set; }

        /// <summary>
        /// 屏蔽区夹角
        /// </summary>
        public float BlindAngle { get; set; }


        /// <summary>
        /// 屏蔽区终止角
        /// </summary>
        public float EndAngle
        {
            get
            {
                return StartAngle + BlindAngle;
            }
        }

        public ICommand SwitchIsSelectedCommand { get; set; }

        internal BlindSectorViewModel(float startAngle, float blindAngle) 
        {
            StartAngle = startAngle;
            BlindAngle = blindAngle;

            SwitchIsSelectedCommand = new RelayCommand(() => IsSelected ^= true );
        }



        public BlindSectorViewModel(BlindSectorConfig blindSector) 
            : this(blindSector.StartAngle, blindSector.BlindAngle)
        { }

        public bool Intersect(BlindSectorConfig other)
        {
            return (other.StartAngle > StartAngle && other.StartAngle < EndAngle)
                || (other.EndAngle > StartAngle && other.EndAngle < EndAngle);
        }
     
        public int CompareTo(object obj)
        {
            if (obj == null) return 1;

            var other = obj as BlindSectorViewModel;
            if (other != null)
                return StartAngle.CompareTo(other.StartAngle);
            else
                throw new ArgumentException($"Object is not a [{typeof(BlindSectorViewModel)}].");
        }

        internal VerticalBlindSectorConfig ToVerticalBlindSectorConfig()
        {
            return new VerticalBlindSectorConfig(StartAngle, BlindAngle);
        }

        internal HorizontalBlindSectorConfig ToHorizontalBlindSectorConfig()
        {
            return new HorizontalBlindSectorConfig(StartAngle, BlindAngle);
        }
    }
}
